package com.dr.cmdb.core.aop;


import com.dr.cmdb.common.log.LoggerUtil;
import com.dr.cmdb.core.annotation.AuditLog;
import com.dr.cmdb.core.listener.event.AuditLogSaveEvent;
import com.dr.cmdb.core.mongodao.OperateLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

/**
 * @ProjectName: cmdb
 * @Package: com.dr.cmdb.application.aop
 * @Description: java类作用描述
 * @Author: duanrui
 * @CreateDate: 2021/4/17 21:36
 * @Version: 1.0
 * <p>
 * Copyright: Copyright (c) 2021
 */
@Aspect
@Component
@Slf4j
public class LogAspect {

    @Autowired
    private ApplicationContext applicationContext;

    @Pointcut("@annotation(com.dr.cmdb.core.annotation.AuditLog)")
    public void logAspectAspect() {
    }


//    @Before("logAspectAspect()")
//    public void before(JoinPoint joinPoint) throws Throwable {
//        //拿到被注解的方法签名
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        //拿到被注解的方法
//        Method method = signature.getMethod();
//        Method targetMethod = AopUtils.getMostSpecificMethod(method, joinPoint.getTarget().getClass());
//        //拿到注解类的参数
//        Object[] arguments = joinPoint.getArgs();
//        //拿到lock参数
//        AuditLog annotation = AnnotationUtils.findAnnotation(targetMethod, AuditLog.class);
//        OperateLog logInfo = OperateLog.builder()
//                .operateDate(new Date())
//                .operateModule(annotation.operateModule())
//                .operateUser("张三")
//                .reqParams(arguments.toString())
//                .reqMethod(method.getName())
//                .operateType(annotation.operateType().getValue())
//                .result(result.toString())
//                .build();
//
//        LoggerUtil.info(log, "操作日志", logInfo.toString());
//        //异步处理日志信息，解耦
//        applicationContext.publishEvent(new AuditLogSaveEvent(this, logInfo));
//    }


    @AfterReturning(returning = "result", value = "logAspectAspect()")
    public void saveAuditLog(JoinPoint joinPoint, Object result) throws Throwable {
        //拿到被注解的方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //拿到被注解的方法
        Method method = signature.getMethod();
        Method targetMethod = AopUtils.getMostSpecificMethod(method, joinPoint.getTarget().getClass());
        //拿到注解类的参数
        Object[] arguments = joinPoint.getArgs();
        //拿到lock参数
        AuditLog annotation = AnnotationUtils.findAnnotation(targetMethod, AuditLog.class);
        OperateLog logInfo = OperateLog.builder()
                .operateDate(new Date())
                .operateModule(annotation.operateModule())
                .operateUser("张三")
                .reqParams(arguments.toString())
                .reqMethod(method.getName())
                .operateType(annotation.operateType().getValue())
                .result(result.toString())
                .build();

        LoggerUtil.info(log, "操作日志", logInfo.toString());
        //异步处理日志信息，解耦
        applicationContext.publishEvent(new AuditLogSaveEvent(this, logInfo));
    }


}
